package net.starwifi.duobao.service.impl;


import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;
import net.starwifi.duobao.FileInfo;
import net.starwifi.duobao.FileInfo.FileType;
import net.starwifi.duobao.FileInfo.OrderType;

import net.starwifi.duobao.SettingUtils;
import net.starwifi.duobao.plugin.StoragePlugin;
import net.starwifi.duobao.service.FileService;
import net.starwifi.duobao.service.PluginService;
import net.starwifi.duobao.utils.FreemarkerUtils;
import net.starwifi.duobao.utils.SFTPChannel;
import net.starwifi.duobao.utils.SFTPConstants;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;

/**
 * Service - 文件
 * 
 * @author ruoo
 * @version 1.0
 */
@Service
public class FileServiceImpl implements FileService, ServletContextAware {

	/** servletContext */
	private ServletContext servletContext;

	@Autowired
	private TaskExecutor taskExecutor;

	@Autowired
	private PluginService pluginService;

	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	/**
	 * 添加上传任务
	 * 
	 * @param storagePlugin
	 *            存储插件
	 * @param path
	 *            上传路径
	 * @param tempFile
	 *            临时文件
	 * @param contentType
	 *            文件类型
	 */
	private void addTask(final StoragePlugin storagePlugin, final String path, final File tempFile, final String contentType) {
		taskExecutor.execute(new Runnable() {
			public void run() {
				try {
					storagePlugin.upload(path, tempFile, contentType);
				} finally {
					FileUtils.deleteQuietly(tempFile);
				}
			}
		});
	}

	public boolean isValid(FileType fileType, MultipartFile multipartFile) {
		if (multipartFile == null) {
			return false;
		}
		Long uploadMaxSize= Long.parseLong(SettingUtils.get("uploadMaxSize"));

		if (uploadMaxSize!= null && uploadMaxSize!= 0 && multipartFile.getSize() > uploadMaxSize * 1024L * 1024L) {
			return false;
		}
		String[] uploadExtensions;
		if (fileType == FileType.flash) {
			uploadExtensions = SettingUtils.get("uploadFlashExtensions").split(",");
		} else if (fileType == FileType.media) {
			uploadExtensions = SettingUtils.get("uploadMediaExtensions").split(",");
		} else if (fileType == FileType.file) {
			uploadExtensions = SettingUtils.get("uploadFileExtensions").split(",");
		} else {
			uploadExtensions = SettingUtils.get("uploadImageExtensions").split(",");
		}
		if (ArrayUtils.isNotEmpty(uploadExtensions)) {
			return FilenameUtils.isExtension(multipartFile.getOriginalFilename(), uploadExtensions);
		}
		return false;
	}

	public static String getUUID(){
		return UUID.randomUUID().toString().replaceAll("-","");
	}



	public String upload(FileType fileType, MultipartFile multipartFile, boolean async){
		String uploadPath="/";
		return upload(fileType, multipartFile, uploadPath, async);
	}

	public String upload(FileType fileType, MultipartFile multipartFile,String uploadPath, boolean async) {
		if (multipartFile == null) {
			return null;
		}
		try {
			String uuid= getUUID();
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("uuid",uuid);
			String path = FreemarkerUtils.process(uploadPath, model);
			String destPath = path + uuid + "." + FilenameUtils.getExtension(multipartFile.getOriginalFilename());
			for (StoragePlugin storagePlugin : pluginService.getStoragePlugins(true)) {
				File tempFile = new File(System.getProperty("java.io.tmpdir") + "/upload_" + UUID.randomUUID() + ".tmp");
				if (!tempFile.getParentFile().exists()) {
					tempFile.getParentFile().mkdirs();
				}
				multipartFile.transferTo(tempFile);
				if (async) {
					addTask(storagePlugin, destPath, tempFile, multipartFile.getContentType());
				} else {
					try {
						storagePlugin.upload(destPath, tempFile, multipartFile.getContentType());
					} finally {
						FileUtils.deleteQuietly(tempFile);
					}
				}
				return storagePlugin.getUrl(destPath);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}



	public String upload(FileType fileType, MultipartFile multipartFile) {
		return upload(fileType, multipartFile, false);
	}

    protected String getExt(MultipartFile file){
        return file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')+1).toLowerCase();
    }

//	@Override
//	public void upload(File file) throws JSchException, SftpException, IOException {
//			Map<String, String> sftpDetails = new HashMap<String, String>();
//			// 设置主机ip，端口，用户名，密码
//			sftpDetails.put(SFTPConstants.SFTP_REQ_HOST, "120.52.21.133");
//			sftpDetails.put(SFTPConstants.SFTP_REQ_USERNAME, "partner100004");
//			sftpDetails.put(SFTPConstants.SFTP_REQ_PASSWORD, "p100004%123");
//			sftpDetails.put(SFTPConstants.SFTP_REQ_PORT, "22");
//			//String src = "c:/3.0/test.txt"; // 本地文件名
////      String dst = "/home/wohuafu/wohuafu/partner100001/INCOMING/AUDIT/"+file.getName(); // 目标文件目录
//			String dst="/INCOMING/AUDIT/"+file.getName();
//			SFTPChannel channel =new SFTPChannel();
//			ChannelSftp chSftp = channel.getChannel(sftpDetails, 60000);
//			chSftp.put(new FileInputStream(file), dst, ChannelSftp.OVERWRITE);
//	}


	public List<FileInfo> browser(String path, FileType fileType, OrderType orderType) {
		if (path != null) {
			if (!path.startsWith("/")) {
				path = "/" + path;
			}
			if (!path.endsWith("/")) {
				path += "/";
			}
		} else {
			path = "/";
		}
		String uploadPath="/";
		/*Setting setting = SettingUtils.get();
		if (fileType == FileType.flash) {
			uploadPath = setting.getFlashUploadPath();
		} else if (fileType == FileType.media) {
			uploadPath = setting.getMediaUploadPath();
		} else if (fileType == FileType.file) {
			uploadPath = setting.getFileUploadPath();
		} else {
			uploadPath = setting.getImageUploadPath();
		}*/
		String browsePath = StringUtils.substringBefore(uploadPath, "${");
		browsePath = StringUtils.substringBeforeLast(browsePath, "/") + path;

		List<FileInfo> fileInfos = new ArrayList<FileInfo>();
		if (browsePath.indexOf("..") >= 0) {
			return fileInfos;
		}
		for (StoragePlugin storagePlugin : pluginService.getStoragePlugins(true)) {
			fileInfos = storagePlugin.browser(browsePath);
			break;
		}
		if (orderType == OrderType.size) {
			Collections.sort(fileInfos, new SizeComparator());
		} else if (orderType == OrderType.type) {
			Collections.sort(fileInfos, new TypeComparator());
		} else {
			Collections.sort(fileInfos, new NameComparator());
		}
		return fileInfos;
	}

	private class NameComparator implements Comparator<FileInfo> {
		public int compare(FileInfo fileInfos1, FileInfo fileInfos2) {
			return new CompareToBuilder().append(!fileInfos1.getIsDirectory(), !fileInfos2.getIsDirectory()).append(fileInfos1.getName(), fileInfos2.getName()).toComparison();
		}
	}

	private class SizeComparator implements Comparator<FileInfo> {
		public int compare(FileInfo fileInfos1, FileInfo fileInfos2) {
			return new CompareToBuilder().append(!fileInfos1.getIsDirectory(), !fileInfos2.getIsDirectory()).append(fileInfos1.getSize(), fileInfos2.getSize()).toComparison();
		}
	}

	private class TypeComparator implements Comparator<FileInfo> {
		public int compare(FileInfo fileInfos1, FileInfo fileInfos2) {
			return new CompareToBuilder().append(!fileInfos1.getIsDirectory(), !fileInfos2.getIsDirectory()).append(FilenameUtils.getExtension(fileInfos1.getName()), FilenameUtils.getExtension(fileInfos2.getName())).toComparison();
		}
	}

}